/*
 * readme:
 * 
 * dont forget to clear int_info before next possible interrupt!
 * 
 * see project wiki
 */

#ifndef EXCEPTIONS_H
#define EXCEPTIONS_H

#ifdef __KERNEL__

#include <asm/desc.h>
#include "from_linux/desc.h"

gate_desc32 *get_idt32(void);
gate_desc32 *set_int32(gate_desc32 *idt, int interrupt, u32 addr);

gate_desc64 *get_idt64(void);
void set_idt64 (gate_desc64 *idt);
void set_int64(gate_desc64 *idt, int interrupt, u64 addr);

void init_test_idt64 (gate_desc64 *idt, u64 handlers, u64 handler_size);
struct desc_ptr make_test_idtr (gate_desc64 *idt);

#endif /* __KERNEL__ */


struct registers_state {
	u64 rax;
	u64 rbx;
	u64 rcx;
	u64 rdx;
	u64 rsi;
	u64 rdi;
	u64 rsp;
	u64 rbp;
	u64 r8;
	u64 r9;
	u64 r10;
	u64 r11;
	u64 r12;
	u64 r13;
	u64 r14;
	u64 r15;
};


#define _STR(val) #val
#define STR(val) _STR(val)

#define SAVE_REGISTER(register) \
		asm volatile("movq %%" STR(register) ", %0" : "=r" (REGISTERS.register))

#define LOAD_REGISTER(register) \
		asm volatile("movq %0, %%" STR(register) : : "r" (REGISTERS.register))

#define SAVE_REGISTERS() {\
		SAVE_REGISTER(rax); \
		SAVE_REGISTER(rbx); \
		SAVE_REGISTER(rcx); \
		SAVE_REGISTER(rdx); \
		SAVE_REGISTER(rsi); \
		SAVE_REGISTER(rdi); \
		SAVE_REGISTER(rsp); \
		SAVE_REGISTER(rbp); \
		SAVE_REGISTER(r8); \
		SAVE_REGISTER(r9); \
		SAVE_REGISTER(r10); \
		SAVE_REGISTER(r11); \
		SAVE_REGISTER(r12); \
		SAVE_REGISTER(r13); \
		SAVE_REGISTER(r14); \
		SAVE_REGISTER(r15); \
}

#define LOAD_REGISTERS() {\
		LOAD_REGISTER(rax); \
		LOAD_REGISTER(rbx); \
		LOAD_REGISTER(rcx); \
		LOAD_REGISTER(rdx); \
		LOAD_REGISTER(rsi); \
		LOAD_REGISTER(rdi); \
		LOAD_REGISTER(rsp); \
		LOAD_REGISTER(rbp); \
		LOAD_REGISTER(r8); \
		LOAD_REGISTER(r9); \
		LOAD_REGISTER(r10); \
		LOAD_REGISTER(r11); \
		LOAD_REGISTER(r12); \
		LOAD_REGISTER(r13); \
		LOAD_REGISTER(r14); \
		LOAD_REGISTER(r15); \
}

#define INTERRUPT_ANCHOR(first_step) \
    asm volatile("movq $100f, %0" : "=r" (PINTERRUPTS->return_addr)); \
    SAVE_REGISTERS(); \
    asm volatile("jmp " first_step); \
    asm volatile("100:"); \
    LOAD_REGISTERS();


#endif /* EXCEPTIONS_H */